/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.rs.service.impl;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import com.xy.biz.base.client.DictClient;
import com.xy.biz.rs.domain.bo.ManufactureArchiveRecordBO;
import com.xy.biz.rs.domain.bo.ManufactureRecordBO;
import com.xy.biz.rs.domain.constants.ManufactureArchiveConstants;
import com.xy.biz.rs.domain.constants.ManufactureRecordConstants;
import com.xy.biz.rs.domain.po.ManufactureArchivePO;
import com.xy.biz.rs.domain.query.ManufactureArchiveRecordQuery;
import com.xy.biz.rs.domain.req.GetManufactureArchiveRequest;
import com.xy.biz.rs.domain.req.ManufactureArchiveApplyCheckRequest;
import com.xy.biz.rs.domain.req.ManufactureArchiveQACheckRequest;
import com.xy.biz.rs.manager.ManufactureArchiveRecordManager;
import com.xy.biz.rs.manager.ManufactureRecordManager;
import com.xy.biz.uc.client.UserClient;
import com.xy.tool.context.UserContextHolder;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.config.ScheduledTask;
import org.springframework.stereotype.Service;

import com.xy.lang.domain.Result;
import com.xy.biz.rs.domain.bo.ManufactureArchiveBO;
import com.xy.biz.rs.domain.query.ManufactureArchiveQuery;
import com.xy.biz.rs.service.ManufactureArchiveService;
import com.xy.biz.rs.manager.ManufactureArchiveManager;
import org.springframework.transaction.annotation.Transactional;

/**
 *
 *
 * @author wwj
 * @date 2021-4-19
 */
@Service
public class ManufactureArchiveServiceImpl implements ManufactureArchiveService {

	@Autowired
	private ManufactureArchiveManager manufactureArchiveManager;
	@Autowired
	private ManufactureArchiveRecordManager manufactureArchiveRecordManager;
	@Autowired
	private ManufactureRecordManager manufactureRecordManager;
	@Autowired
	private DictClient dictClient;
	@Autowired
	private UserClient userClient;

	@Transactional
	@Override
	public Result<?> saveManufactureArchive(ManufactureArchiveBO manufactureArchiveBO) {
		List<ManufactureArchiveBO> manufactureArchiveBOS = manufactureArchiveManager.listManufactureArchive(ManufactureArchiveQuery.one()
				.productDictCode(manufactureArchiveBO.getProductDictCode())
				.subProductDictCode(manufactureArchiveBO.getSubProductDictCode())
				.batchCode(manufactureArchiveBO.getBatchCode()).build());
		Long manufactureArchiveId;
		if (CollectionUtils.isEmpty(manufactureArchiveBOS) || manufactureArchiveBOS.size() == 0) {
			buildBO(manufactureArchiveBO);
			ManufactureArchivePO manufactureArchivePO = manufactureArchiveManager.saveManufactureArchive(manufactureArchiveBO);
			manufactureArchiveId = manufactureArchivePO.getManufactureArchiveId();
		}else {
			manufactureArchiveId = manufactureArchiveBOS.get(0).getManufactureArchiveId();
		}

		int row = manufactureArchiveRecordManager.countManufactureArchiveRecord(ManufactureArchiveRecordQuery.builder()
				.manufactureArchiveId(manufactureArchiveId)
				.manufactureRecordId(manufactureArchiveBO.getManufactureRecordId()).build());
		if (row == 0) {
			manufactureArchiveRecordManager.saveManufactureArchiveRecord(ManufactureArchiveRecordBO.builder()
					.createTime(LocalDateTime.now())
					.deleteFlag(false)
					.manufactureArchiveId(manufactureArchiveId)
					.manufactureRecordId(manufactureArchiveBO.getManufactureRecordId())
					.tenantId(UserContextHolder.getTenantId())
					.build());
		}
		manufactureRecordManager.updateManufactureRecord(ManufactureRecordBO.builder()
				.manufactureRecordId(manufactureArchiveBO.getManufactureRecordId())
				.status(ManufactureRecordConstants.STATUS_APPROVE_BATCH).build());
		return Result.success();
	}

	private void buildBO(ManufactureArchiveBO manufactureArchiveBO) {
		manufactureArchiveBO.setCreateTime(LocalDateTime.now());
		manufactureArchiveBO.setCreateUserId(UserContextHolder.getUserId());
		manufactureArchiveBO.setDeleteFlag(false);
		manufactureArchiveBO.setTenantId(UserContextHolder.getTenantId());
		manufactureArchiveBO.setUpdateTime(LocalDateTime.now());
		manufactureArchiveBO.setStatus(ManufactureArchiveConstants.STATUS_UNAPPLY);
	}

	@Override
	public Result<?> saveAllManufactureArchive(Collection<ManufactureArchiveBO> collection) {
		int affectedRows = manufactureArchiveManager.saveAllManufactureArchive(collection);
		if (affectedRows > 0) {
			return Result.success();
		}
		return Result.ofErrorRowsAffected();
	}

	@Override
	public Result<?> updateManufactureArchive(ManufactureArchiveBO manufactureArchiveBO) {
		int affectedRows = manufactureArchiveManager.updateManufactureArchive(manufactureArchiveBO);
		if (affectedRows > 0) {
			return Result.success();
		}
		return Result.ofErrorRowsAffected();
	}

	@Override
	public Result<?> deleteManufactureArchive(Long manufactureArchiveId) {
		int affectedRows = manufactureArchiveManager.deleteManufactureArchive(manufactureArchiveId);
		if (affectedRows > 0) {
			return Result.success();
		}
		return Result.ofErrorRowsAffected();
	}

	@Override
	public ManufactureArchiveBO getManufactureArchive(Long manufactureArchiveId) {
		return manufactureArchiveManager.getManufactureArchive(manufactureArchiveId);
	}

	@Override
	public List<ManufactureArchiveBO> listManufactureArchiveById(Collection<Long> collection) {
		return manufactureArchiveManager.listManufactureArchiveById(collection);
	}

	@Override
	public List<ManufactureArchiveBO> listManufactureArchive(ManufactureArchiveQuery query) {

		List<ManufactureArchiveBO> manufactureArchiveBOS = manufactureArchiveManager.listManufactureArchive(query);
		if (CollectionUtils.isEmpty(manufactureArchiveBOS)) {
			return manufactureArchiveBOS;
		}
		dictClient.buildByDict(manufactureArchiveBOS,"product",bo->bo.getProductDictCode(),(bo,value)->bo.setProductDictValue(value));
		dictClient.buildByDict(manufactureArchiveBOS,"product",bo->bo.getSubProductDictCode(),(bo,value)->bo.setSubProductDictValue(value));
		List<Long> checkUserIds = manufactureArchiveBOS.stream().map(ManufactureArchiveBO::getCheckUserId).collect(Collectors.toList());
		userClient.buildByUser(manufactureArchiveBOS,checkUserIds,ManufactureArchiveBO::getCheckUserId,(bo,u)->bo.setCheckUserName(u.getUserName()));
		List<Long> createUserIds = manufactureArchiveBOS.stream().map(ManufactureArchiveBO::getCreateUserId).collect(Collectors.toList());
		userClient.buildByUser(manufactureArchiveBOS,createUserIds,ManufactureArchiveBO::getCreateUserId,(bo,u)->bo.setCreateUserName(u.getUserName()));
		Set<Long> archIds = manufactureArchiveBOS.stream().map(ManufactureArchiveBO::getManufactureArchiveId).collect(Collectors.toSet());
		List<ManufactureArchiveRecordBO> manufactureArchiveRecordBOS = manufactureArchiveRecordManager.listManufactureArchiveRecord(ManufactureArchiveRecordQuery.max()
				.manufactureArchiveIds(archIds).build());
		Map<Long, Long> recordCountMap = manufactureArchiveRecordBOS.stream().collect(Collectors.groupingBy(ManufactureArchiveRecordBO::getManufactureArchiveId, Collectors.counting()));
		for (ManufactureArchiveBO manufactureArchiveBO : manufactureArchiveBOS) {
			manufactureArchiveBO.setRecordCount(recordCountMap.get(manufactureArchiveBO.getManufactureArchiveId()));
		}
		return manufactureArchiveBOS;
	}

	@Override
	public int countManufactureArchive(ManufactureArchiveQuery query) {
		return manufactureArchiveManager.countManufactureArchive(query);
	}

    @Override
    public List<ManufactureRecordBO> detail(GetManufactureArchiveRequest request) {
        HashSet<Long> archIds = new HashSet<>();
        archIds.add(request.getManufactureArchiveId());
        List<ManufactureArchiveRecordBO> manufactureArchiveRecordBOS = manufactureArchiveRecordManager.listManufactureArchiveRecord(ManufactureArchiveRecordQuery.max()
                .manufactureArchiveIds(archIds).build());
		List<Long> recordIds = manufactureArchiveRecordBOS.stream().map(ManufactureArchiveRecordBO::getManufactureRecordId).collect(Collectors.toList());
		List<ManufactureRecordBO> manufactureRecordBOS = manufactureRecordManager.listManufactureRecordById(recordIds);
		dictClient.buildByDict(manufactureRecordBOS,"product",bo->bo.getProductDictCode(),(bo,value)->bo.setProductDictValue(value));
		dictClient.buildByDict(manufactureRecordBOS,"product",bo->bo.getSubProductDictCode(),(bo,value)->bo.setSubProductDictValue(value));
		return manufactureRecordBOS;
    }

	@Override
	public Result<Object> applyCheck(ManufactureArchiveApplyCheckRequest request) {
		int row = manufactureArchiveManager.updateManufactureArchive(ManufactureArchiveBO.builder()
				.manufactureArchiveId(request.getManufactureArchiveId())
				.checkUserId(request.getQAUserId())
				.status(ManufactureArchiveConstants.STATUS_APPLY)
				.updateTime(LocalDateTime.now()).build());
		if (row > 0) {
			return Result.success();
		}
		return Result.fail();
	}

	@Override
	public Result<?> check(ManufactureArchiveQACheckRequest request) {
		int row = manufactureArchiveManager.updateManufactureArchive(ManufactureArchiveBO.builder()
				.manufactureArchiveId(request.getManufactureArchiveId())
				.status(ManufactureArchiveConstants.STATUS_APPROVED)
				.updateTime(LocalDateTime.now()).build());
		if (row > 0) {
			return Result.success();
		}
		return Result.fail();
	}

}
